﻿using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.Validation;
using Newtonsoft.Json;
using RulesEngine.Models;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace EasyXaf.LowCode.RulesEngineEditors.Models;

[DomainComponent]
[XafDisplayName("执行规则动作")]
[XafDefaultProperty(nameof(DisplayName))]
public class EvaluateRuleActionObject : ActionObject
{
    private string _workflowName;
    private string _ruleName;

    [Browsable(false)]
    [RuleRequiredField]
    [XafDisplayName("名称")]
    public override string Name => "EvaluateRule";

    [XafDisplayName("名称")]
    public override string DisplayName => "执行规则动作";

    [XafDisplayName("描述")]
    [VisibleInDetailView(false)]
    public override string Description => $"{WorkflowName} -> {RuleName}";

    [RuleRequiredField]
    [XafDisplayName("工作流名称")]
    public string WorkflowName
    {
        get => _workflowName;
        set => SetPropertyValue(ref _workflowName, value);
    }

    [RuleRequiredField]
    [XafDisplayName("规则名称")]
    public string RuleName
    {
        get => _ruleName;
        set => SetPropertyValue(ref _ruleName, value);
    }

    [XafDisplayName("输入过滤")]
    public ObservableCollection<InputFilterObject> InputFilters { get; } = new();

    [XafDisplayName("附加输入")]
    public ObservableCollection<ScopedParamObject> AdditionalInputs { get; } = new();

    public override IEnumerable<ValidationResult> Validate()
    {
        foreach (var validationResult in base.Validate())
        {
            yield return validationResult;
        }

        if (string.IsNullOrWhiteSpace(Name))
        {
            yield return new ValidationResult("执行规则动作的名称不能为空", ValidationResultLevel.Error);
        }

        if (string.IsNullOrWhiteSpace(WorkflowName))
        {
            yield return new ValidationResult("执行规则动作的工作流名称不能为空", ValidationResultLevel.Error);
        }

        if (string.IsNullOrWhiteSpace(RuleName))
        {
            yield return new ValidationResult("执行规则动作的规则名称不能为空", ValidationResultLevel.Error);
        }

        foreach (var inputFilter in InputFilters)
        {
            foreach (var validationResult in inputFilter.Validate())
            {
                yield return validationResult;
            }
        }

        foreach (var additionalInput in AdditionalInputs)
        {
            foreach (var validationResult in additionalInput.Validate())
            {
                yield return validationResult;
            }
        }
    }

    public override ActionInfo ToActionInfo()
    {
        var actionInfo = new ActionInfo
        {
            Name = Name,
            Context = new Dictionary<string, object>()
        };

        actionInfo.Context["workflowName"] = WorkflowName;
        actionInfo.Context["ruleName"] = RuleName;

        if (InputFilters.Any())
        {
            actionInfo.Context["inputFilter"] = InputFilters.Select(f => f.Filter).ToArray();
        }

        if (AdditionalInputs.Any())
        {
            actionInfo.Context["additionalInputs"] = AdditionalInputs
                .Select(a => new
                {
                    a.Name,
                    a.Description,
                    ExpressionType = ExpressionTypeConverter.ToString(a.ExpressionType),
                    a.TargetObject,
                    a.Expression,
                })
                .ToArray();
        }

        return actionInfo;
    }

    public static EvaluateRuleActionObject FromActionInfo(ActionInfo actionInfo)
    {
        if (actionInfo.Context != null && actionInfo.Context.ContainsKey("workflowName") && actionInfo.Context.ContainsKey("ruleName"))
        {
            var actionObject = new EvaluateRuleActionObject()
            {
                WorkflowName = actionInfo.Context["workflowName"] as string,
                RuleName = actionInfo.Context["ruleName"] as string,
            };

            if (actionInfo.Context.ContainsKey("inputFilter"))
            {
                var json = JsonConvert.SerializeObject(actionInfo.Context["inputFilter"]);
                var filters = JsonConvert.DeserializeObject<List<string>>(json);
                if (filters != null)
                {
                    foreach (var filter in filters)
                    {
                        actionObject.InputFilters.Add(new InputFilterObject
                        {
                            Filter = filter,
                        });
                    }
                }
            }

            if (actionInfo.Context.ContainsKey("additionalInputs"))
            {
                var json = JsonConvert.SerializeObject(actionInfo.Context["additionalInputs"]);
                var scopedParams = JsonConvert.DeserializeObject<List<ScopedParamObject>>(json);
                if (scopedParams != null)
                {
                    foreach (var parameter in scopedParams)
                    {
                        actionObject.AdditionalInputs.Add(parameter);
                    }
                }
            }

            return actionObject;
        }

        return null;
    }
}
